#include <signal.h>
#include <wait.h>
#include "wrap.h"

/* 这是一个使用多进程来实现高并发的服务器*/

#define SERV_PORT 8888

// 捕捉子进程函数，以便处理僵尸进程
void catch_chile(int signum){
	while(waitpid(0, NULL, WNOHANG) > 0);
	return ;
}

void tcp_ip_server(){
	// sfd为服务器的文件描述符
	// cfd为由sfd是创建出来的套接字文件描述符
	int sfd, cfd, i, ret, clit_addr_len;
	struct sockaddr_in serv_addr, clit_addr;
	char buf[1024], clit_addr_buf[1024];
	pid_t pid;

	bzero(&serv_addr,sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERV_PORT);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	// 1. 创建socket套接字
	sfd = Socket(AF_INET, SOCK_STREAM, 0);
	// 2. 使用bind进行IP地址和端口的绑定
	Bind(sfd,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
	// 3. 使用listen进行连接数量的设定
	Listen(sfd,2);
	// 4. 使用accetp函数进行监测
	while(1){
		clit_addr_len = sizeof(clit_addr);
		bzero(&clit_addr, clit_addr_len);
		cfd = Accept(sfd, (struct sockaddr*)&clit_addr, &clit_addr_len);
		
		// 打印客户端的端口号和ＩＰ地址
		printf("IP:%s,  Port:%d\n", inet_ntop(AF_INET, &clit_addr.sin_addr.s_addr, clit_addr_buf, sizeof(clit_addr_buf)), ntohs(clit_addr.sin_port));
		pid = fork();
		if(pid == 0){
		    while(1){
			// 在子进程中进行TCP/IP通信
			close(sfd);
			// 5. 使用Read和Write函数进行读写
			ret = Read(cfd, buf, sizeof(buf));
			if(ret == 0){
				close(cfd);
				exit(1);
			}
			
			Write(STDOUT_FILENO,buf,ret);
			//printf("\n");
			//printf("%s\n", buf);

			for(i = 0;i < ret; ++i){
				buf[i] = toupper(buf[i]);
			}
			Write(cfd,buf,ret);
			bzero(buf,sizeof(buf));
				
			// 服务器给客户端发送数据
			//scanf("%s",buf);
			/*fgets(buf,sizeof(buf), stdin);
			ret = Write(cfd, buf, sizeof(buf));
			if(ret ==0 ){
				close(cfd);
				exit(1);
			}*/
			//printf("%s\n", buf);
		    }
		}else{
		  	// 在父进程中处理退出的子进程，避免僵尸进行的存在
			struct sigaction act;

			act.sa_handler = catch_chile;
			sigemptyset(&act.sa_mask);
			act.sa_flags = 0;

			ret = sigaction(SIGCHLD, &act, NULL);
			if(ret == -1) sys_err("sigaction error");

		      	close(cfd);
		}
	}
	close(sfd);
	
}

int main(){
	tcp_ip_server();
}
